iT邦幫忙

2024 iThome 鐵人賽

DAY 16
1

提供更多範例,讓使用者了解此元件用法吧。◝( •ω• )◟

發射參數

調整發射速度向量,就可以往任意方向發射。

src\components\util-party-popper\examples\emit-params.vue

<template>
  <div class="flex flex-col gap-4 w-full border border-gray-300">
    <div class=" flex flex-col p-4 m-4 border ">
      <div class="flex gap-6">
        <label class="flex-1 text-right">
          x 軸速度
        </label>

        <input
          v-model.number="param.velocity.x"
          type="range"
          min="-8"
          max="8"
          class="flex-[3]"
        >

        <div class="w-6 text-right">
          {{ param.velocity.x }}
        </div>
      </div>

      <div class="flex gap-6">
        <label class="flex-1 text-right">
          y 軸速度
        </label>

        <input
          v-model.number="param.velocity.y"
          type="range"
          min="-8"
          max="8"
          class="flex-[3]"
        >

        <div class="w-6 text-right">
          {{ param.velocity.y }}
        </div>
      </div>
    </div>

    <div
      ref="containerRef"
      class=" relative flex justify-center items-center h-[50vh]"
    >
      <util-party-popper
        ref="popperRef"
        class=" absolute w-full h-full pointer-events-none"
        v-bind="param"
        :max-concurrency="50"
      />

      <div
        class=" border px-8 py-4 rounded select-none cursor-pointer  bg-white z-10"
        @click="emit()"
      >
        發射
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue';

import UtilPartyPopper from '../util-party-popper.vue';

import { useElementSize } from '@vueuse/core';

const param = ref({
  quantityOfPerEmit: 20,
  velocity: {
    x: 0,
    y: 8,
  }
});

const popperRef = ref<InstanceType<typeof UtilPartyPopper>>();
const containerRef = ref<HTMLDivElement>();

/** 容器尺寸 */
const containerSize = reactive(useElementSize(containerRef))

function emit() {
  // 從按鈕正中間發射
  popperRef.value?.emit(() => ({
    x: containerSize.width / 2,
    y: containerSize.height / 2,
    velocity: param.value.velocity,
  }));
}
</script>

在文件中引入範例。

docs\components\util-party-popper\index.md

...

<script setup>
...
import EmitParams from '../../../src/components/util-party-popper/examples/emit-params.vue'
</script>

...

### 發射參數

可以調整每一次發射的速度方向。

<emit-params />

::: details 查看範例原始碼
<<< ../../../src/components/util-party-popper/examples/emit-params.vue
:::

...

自由調整噴射方向。◝( •ω• )◟

動畫.gif

廣域發射

不只有單點發射,廣域發射更有派對的感覺。✧⁑。٩(ˊᗜˋ*)و✧⁕。

src\components\util-party-popper\examples\wide-area-emit.vue

<template>
  <div class="flex flex-col gap-4 w-full">
    <div class=" w-full h-full flex justify-center items-center gap-10 p-10">
      <div
        class=" bg-white text-2xl rounded px-4 py-2 select-none cursor-pointer"
        @click="emit('left')"
      >
        👈
      </div>

      <div class="flex flex-col gap-10">
        <div
          class="bg-white text-2xl rounded px-4 py-2 select-none cursor-pointer"
          @click="emit('top')"
        >
          👆
        </div>

        <div
          class="bg-white text-2xl rounded px-4 py-2 select-none cursor-pointer"
          @click="emit('bottom')"
        >
          👇
        </div>
      </div>

      <div
        class="bg-white text-2xl rounded px-4 py-2 select-none cursor-pointer"
        @click="emit('right')"
      >
        👉
      </div>
    </div>

    <util-party-popper
      ref="popperRef"
      class=" !fixed left-0 top-0 w-full h-full z-50 pointer-events-none"
      :quantity-of-per-emit="50"
      :max-concurrency="50"
    />
  </div>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue';
import { Scalar } from '@babylonjs/core';

import UtilPartyPopper from '../util-party-popper.vue';

import { useWindowSize } from '@vueuse/core';

const popperRef = ref<InstanceType<typeof UtilPartyPopper>>();
const windowSize = reactive(useWindowSize());

function emit(position: 'top' | 'bottom' | 'left' | 'right') {
  const popperEmit = popperRef.value?.emit;
  if (!popperEmit) return;

  const offset = 10;

  if (position === 'top') {
    popperEmit(() => ({
      x: Scalar.RandomRange(0, windowSize.width),
      y: -offset,
      velocity: {
        x: Scalar.RandomRange(1, -1),
        y: Scalar.RandomRange(0, -10)
      },
    }))
    return;
  }

  if (position === 'bottom') {
    popperEmit(() => ({
      x: Scalar.RandomRange(0, windowSize.width),
      y: windowSize.height + offset,
      velocity: {
        x: Scalar.RandomRange(1, -1),
        y: Scalar.RandomRange(10, 15)
      },
    }))
    return;
  }

  if (position === 'left') {
    popperEmit(() => ({
      x: -offset,
      y: Scalar.RandomRange(0, windowSize.height),
      velocity: {
        x: Scalar.RandomRange(5, 10),
        y: Scalar.RandomRange(-1, 1)
      },
    }))
    return;
  }

  if (position === 'right') {
    popperEmit(() => ({
      x: windowSize.width + offset,
      y: Scalar.RandomRange(0, windowSize.height),
      velocity: {
        x: Scalar.RandomRange(-5, -10),
        y: Scalar.RandomRange(-1, 1)
      },
    }))
    return;
  }
}
</script>

在文件中引入範例。

docs\components\util-party-popper\index.md

...

<script setup>
...
import WideAreaEmit from '../../../src/components/util-party-popper/examples/wide-area-emit.vue'
</script>

...

### 廣域發射

不只有速度,粒子發射範圍也可以調整。

<wide-area-emit />

::: details 查看範例原始碼
<<< ../../../src/components/util-party-popper/examples/wide-area-emit.vue
:::

...

開派對囉!(/≧▽≦)/

動畫.gif

最後讓我們補充一下原理簡介。

docs\components\util-party-popper\index.md

...

## 原理

利用 babylon.js 的 SolidParticleSystem 製作粒子效果。

📚 [An Introduction To The Solid Particle System](https://doc.babylonjs.com/features/featuresDeepDive/particles/solid_particle_system/sps_intro)

...

總結

  • 新增「發射參數」範例,展示如何調整發射方向
  • 新增「廣域發射」範例,展示更好的視覺效果

以上程式碼已同步至 GitLab,大家可以前往下載:

GitLab - D16


上一篇
D15 - 拉炮:單元測試
下一篇
D17 - 拉炮:e2e 測試
系列文
要不要 Vue 點酷酷的元件?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言